package main

import "fmt"

/*
问题：一个string类型的值在底层是怎样被表达的？
	是在底层，一个string类型的值是由一系列相对应的 Unicode 代码点的 UTF-8 编码值来表达的.

	在 Go 语言中，一个string类型的值既可以被拆分为一个包含多个字符的序列，也可以被拆分为一个包含多个字节的序列。
	前者可以由一个以rune为元素类型的切片来表示，而后者则可以由一个以byte为元素类型的切片代表。
	rune是 Go 语言特有的一个基本数据类型，它的一个值就代表一个字符，即：一个 Unicode 字符。

	type rune = int32
	根据rune类型的声明可知，它实际上就是int32类型的一个别名类型。也就是说，一个rune类型的值会由四个字节宽度的空间来存储。

	一个string类型的值会由若干个 Unicode 字符组成，每个 Unicode 字符都可以由一个rune类型的值来承载。

问题 1：使用带有range子句的for语句遍历字符串值的时候应该注意什么？

	带有range子句的for语句会先把被遍历的字符串值拆成一个字节序列，然后再试图找出这个字节序列中包含的每一个 UTF-8 编码值，或者说每一个 Unicode 字符。
	这样的for语句可以为两个迭代变量赋值。如果存在两个迭代变量，那么赋给第一个变量的值，就将会是当前字节序列中的某个 UTF-8 编码值的第一个字节所对应的那个索引值。
    而赋给第二个变量的值，则是这个 UTF-8 编码值代表的那个 Unicode 字符，其类型会是rune。



*/

func main() {

	str :="Go爱好者"
	fmt.Printf("The string: %q \n", str)
	// 字符串值"Go爱好者"如果被转换为[]rune类型的值的话，其中的每一个字符（不论是英文字符还是中文字符）就都会独立成为一个rune类型的元素值。
	fmt.Printf(" => runes(char): %q\n", [] rune(str))
	//
	fmt.Printf(" => runes(hex): %x\n", [] rune(str))
	fmt.Printf(" => bytes(hex): [% x]\n", [] byte(str))

	/*
		第一行内容中的关键信息有0、'G'和[47]。这是由于这个字符串值中的第一个 Unicode 字符是'G'。该字符是一个单字节字符，并且由相应的字节序列中的第一个字节表达。这个字节的十六进制表示为47。
		0: 'G' [47]
		第二行展示的内容与之类似，即：第二个 Unicode 字符是'o'，由字节序列中的第二个字节表达，其十六进制表示为6f。
		1: 'o' [6f]
		第三行展示的是'爱'，也是第三个 Unicode 字符。因为它是一个中文字符，所以由字节序列中的第三、四、五个字节共同表达，其十六进制表示也不再是单一的整数，而是e7、88和b1组成的序列。
		2: '爱' [e7 88 b1]
		因为'爱'是由三个字节共同表达的，所以第四个 Unicode 字符'好'对应的索引值并不是3，而是2加3后得到的5。这里的2代表的是'爱'对应的索引值，而3代表的则是'爱'对应的 UTF-8 编码值的宽度。
		5: '好' [e5 a5 bd]
		8: '者' [e8 80 85]

	*/
	for index, ch := range str {
		fmt.Printf("%d: %q [% x]\n", index, ch, []byte(string(ch)))
	}

}
